
package com.android.finaltracer.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import android.util.Log;

import com.android.finaltracer.bean.SuppressSerialize;

/**
 * @author guhl1
 */
public class Bean {

    private final static String TAG = Bean.class.getSimpleName();

    private Bean() {

    }

    public static Map<String, Object> bean2Map(Object bean) {
        if (bean != null) {
            Map<String, Object> result = new HashMap<String, Object>();
            List<Field> fields = getFieldsByClass(bean.getClass());
            for (Iterator<Field> it = fields.iterator(); it.hasNext();) {
                Field field = (Field) it.next();
                field.setAccessible(true);
                String name = field.getName();
                try {
                    Object value = field.get(bean);
                    result.put(name, value);
                } catch (Exception e) {
                    Log.e(TAG, "error", e);
                }
            }
            return result;
        }
        return null;
    }

    public static <T> T map2Bean(Map<String, String> map, Class<T> desClass) {
        if (desClass == null) {
            Log.w(TAG, "desClass is null ");
            return null;
        }
        List<Field> fields = getFieldsByClass(desClass);
        try {
            T t = desClass.newInstance();
            for (Iterator<Field> it = fields.iterator(); it.hasNext();) {
                Field field = it.next();
                field.setAccessible(true);
                String name = field.getName();
                Object value = map.get(name);
                Class<?> type = field.getType();
                if (type.equals(String.class)) {
                } else if (type.getName().equals("int")
                        || type.equals(Integer.class)) {
                    value = value == null ? 0 : Integer.parseInt(value
                            .toString());
                } else if (type.getName().equals("double")
                        || type.equals(Double.class)) {
                    value = value == null ? 0 : Double.parseDouble(value
                            .toString());
                } else if (type.getName().equals("long")
                        || type.equals(Long.class)) {
                    value = value == null ? 0 : Long
                            .parseLong(value.toString());
                } else {
                    throw new RuntimeException(type.getSimpleName()
                            + " not supported yet");
                }
                field.set(t, value);
            }
            return t;
        } catch (Exception e) {
            Log.e(TAG, "error", e);
        }
        return null;
    }

    private static List<Field> getFieldsByClass(Class<? extends Object> clazz) {
        List<Field> result = new ArrayList<Field>();
        if (clazz != null && !clazz.equals(Object.class)) {
            Field[] fields = clazz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                int modi = field.getModifiers();
                if (Modifier.isPrivate(modi) && !Modifier.isFinal(modi)
                        && !Modifier.isStatic(modi)) {
                    if (!field.isAnnotationPresent(SuppressSerialize.class)) {
                        result.add(field);
                    }
                }
            }
            Class<? extends Object> superClazz = clazz.getSuperclass();
            if (superClazz != null && !superClazz.equals(Object.class)) {
                result.addAll(getFieldsByClass(superClazz));
            }
        }
        return result;
    }
}
